#include "servo.h"
#include <avr/interrupt.h>

void initServo()
{
  uint8_t oldSREG = SREG;

  cli();
  /* Fast PWM, ICR1 is top */
  TCCR1A = _BV(WGM11);

  /* Fast PWM, ICR1 is top  with /8 prescaler*/
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11);

  OCR1A = 3000;
  OCR1B = 3000;

  // 20000 uS is a bit fast for the refresh, 20ms, but 
  ICR1 = clockCyclesPerMicrosecond()*(20000L/8);
  // it keeps us from overflowing ICR1 at 20MHz clocks
  // That "/8" at the end is the prescaler.
  
#if defined(__AVR_ATmega328P__) 
  // In Jim Studt's (jim@federated.com) code the next line was
  // TIMSK0 &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
  // But it did not seem to work and was changed following a suggestion
  // by Terry Thrift (terry@thrift.com)
  TIMSK1 &= ~( _BV(ICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
#else
  TIMSK &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
#endif
  SREG = oldSREG;  // undo cli()    
}

#define NO_ANGLE 1500

uint8_t attachServo(ServoState *state)
{
  if ( state->pin != PB1 && state->pin != PB2) return 1;

  //pin = pinArg;
  //angle = NO_ANGLE;
  //digitalWrite(pin,0);
  //pinMode(pin,OUTPUT);
  DDRB |= (1 << state->pin);
    

  //if ( !attached9 && !attached10) this->init();

  // muck with timer flags
  if ( state->pin == PB1) 
  {
	 // attached9 = 1;
	  TCCR1A = TCCR1A & ~_BV(COM1A0) | _BV(COM1A1);
  } 
  else 
  {
	  //attached10 = 1;
	  TCCR1A = TCCR1A & ~_BV(COM1B0) | _BV(COM1B1);
  }

  return 0;
}

void detachServo(ServoState *state)
{
  // muck with timer flags
  if ( state->pin == PB1) 
  {
	  //attached9 = 0;
	  TCCR1A = TCCR1A & ~_BV(COM1A0) & ~_BV(COM1A1);
  }
  else
  {
	  //attached10 = 0;
	  TCCR1A = TCCR1A & ~_BV(COM1B0) & ~_BV(COM1B1);
  }
  
  //pinMode(pin,INPUT);

  //if ( !attached9 && !attached10) releaseTimer1();
}

void write_ms(ServoState *state)
{
  uint16_t p;

  if ( state->ms < 500)
  {
    state->ms = 500;
  }

  if ( state->ms > 2500)
  {
    state->ms = 2500;
  }

  // Calculate the angle from the MS
  //angle = angleArg;

    
  p = ((state->ms * clockCyclesPerMicrosecond()) /8); 

  if ( state->pin == PB1)
  {
    OCR1A = p;
  }
  else
  {
    OCR1B = p;
  }
    
}
void write_deg(ServoState *state)
{
  //uint16_t p;

  if ( state->angle < 0)
  {
    state->angle = 0;
  }

  if ( state->angle > 180)
  {
    state->angle = 180;
  }

  state->ms = (state->angle * 11) + 500;
    
  write_ms(state); 
}
/*
uint8_t attached()
{
    if ( pin == PB1 && attached9)
    {
      return 1;
    }

    if ( pin == PB2 && attached10)
    {
      return 1;
    }

    return 0;

  return 0;
}*/


